Skip to content

Prevent overlapping referral program editions#1986

Merged
Goader merged 5 commits intomainfrom
task/prevent-edition-overlap
Apr 25, 2026
Merged

Prevent overlapping referral program editions#1986
Goader merged 5 commits intomainfrom
task/prevent-edition-overlap

Conversation

@Goader
Copy link
Copy Markdown
Member

@Goader Goader commented Apr 23, 2026

Prevent overlapping referral program editions

closes: #1959

Summary

  • Added base referral program edition config type to be a common root between config and summary types
  • Added verification for the overlap

Why


Testing

  • Automatic CI and manual validation
  • Added new tests for the added functionality

Pre-Review Checklist (Blocking)

  • This PR does not introduce significant changes and is low-risk to review quickly.
  • Relevant changesets are included (or are not required)

@Goader Goader self-assigned this Apr 23, 2026
Copilot AI review requested due to automatic review settings April 23, 2026 00:57
@Goader Goader requested a review from a team as a code owner April 23, 2026 00:57
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 23, 2026

🦋 Changeset detected

Latest commit: df1b847

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
Name Type
@namehash/ens-referrals Major
ensapi Major
ensindexer Major
ensadmin Major
ensrainbow Major
fallback-ensapi Major
enssdk Major
enscli Major
enskit Major
ensskills Major
@ensnode/datasources Major
@ensnode/ensrainbow-sdk Major
@ensnode/ensdb-sdk Major
@ensnode/ensnode-react Major
@ensnode/ensnode-sdk Major
@ensnode/integration-test-env Major
@ensnode/ponder-sdk Major
@ensnode/ponder-subgraph Major
@ensnode/shared-configs Major
@docs/ensnode Major
@docs/ensrainbow Major
@namehash/namehash-ui Major
@ensnode/enskit-react-example Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

3 Skipped Deployments
Project Deployment Actions Updated (UTC)
admin.ensnode.io Skipped Skipped Apr 25, 2026 0:25am
ensnode.io Skipped Skipped Apr 25, 2026 0:25am
ensrainbow.io Skipped Skipped Apr 25, 2026 0:25am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 23, 2026

Warning

Rate limit exceeded

@Goader has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 37 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 9 minutes and 37 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6e4bb041-4b4f-4d4d-9932-4a4343615dd4

📥 Commits

Reviewing files that changed from the base of the PR and between 346fb88 and df1b847.

📒 Files selected for processing (1)
  • packages/ens-referrals/src/edition.test.ts
📝 Walkthrough

Walkthrough

Adds a shared base edition config type, enforces inclusive non‑overlapping time ranges per subregistryId, refactors Zod schemas to use the base schema, exposes per-award-model Zod schemas via the internal entrypoint, and updates tests and changesets accordingly.

Changes

Cohort / File(s) Summary
Changesets
.changeset/bright-rivers-flow.md, .changeset/quiet-mirrors-shine.md, .changeset/shiny-tigers-wander.md
Three changeset metadata files documenting minor releases: base config type, internal Zod schema exports, and non-overlapping-editions constraint.
Core types & validation
packages/ens-referrals/src/edition.ts, packages/ens-referrals/src/award-models/shared/edition-summary.ts
Introduce BaseReferralProgramEditionConfig; make summary extend base; add findOverlappingEditionPair and enforce inclusive non-overlap invariant when building/validating edition sets.
Zod schema refactor & enforcement
packages/ens-referrals/src/api/zod-schemas.ts, packages/ens-referrals/src/award-models/shared/api/zod-schemas.ts
Create makeReferralProgramEditionSlugSchema and makeBaseReferralProgramEditionConfigSchema; refactor summary schema to build from base; replace local schemas with shared imports; add overlap detection and custom Zod issues for editions and summaries.
Award-model internal exports
packages/ens-referrals/src/internal.ts
Re-export Zod schemas for pie-split, rev-share-cap, and shared award-models via internal entrypoint.
Tests — unit & api
packages/ens-referrals/src/edition.test.ts, packages/ens-referrals/src/api/zod-schemas.test.ts
Add tests for overlap detection (interior and boundary-touching overlaps treated as overlapping), adjust fixtures/timings, and extend config-set & summary parsing tests to assert invariant.
Test adjustments (consumer)
apps/ensapi/src/handlers/ensanalytics/ensanalytics-api.test.ts
Mock per-edition ReferrerLeaderboard objects with rules derived from each edition config instead of sharing a single leaderboard instance.
Docs / metadata
docs/ensnode.io/ensapi-openapi.json
Bump OpenAPI info.version from 1.10.0 to 1.10.1.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

ensanalytics

Poem

🐰 I boxed the editions, hopped them in line,

No overlaps now — each subregistry's fine.
Schemas shared neatly, tests give a cheer,
Internal exports hop forward this year.
A tiny rabbit codex: tidy and clear.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Prevent overlapping referral program editions' directly and accurately summarizes the main change in the PR.
Description check ✅ Passed The PR description follows the template structure with summary, why, testing, and pre-review checklist completed.
Linked Issues check ✅ Passed All coding requirements from issue #1959 are met: base edition config type added, overlap validation implemented with inclusive time bounds, and comprehensive tests added.
Out of Scope Changes check ✅ Passed All changes are directly related to preventing edition overlap and supporting infrastructure (changesets, test updates, OpenAPI version bump).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch task/prevent-edition-overlap

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 23, 2026

Greptile Summary

This PR adds a BaseReferralProgramEditionConfig interface as a common parent for ReferralProgramEditionConfig and BaseReferralProgramEditionSummary, then enforces a per-subregistryId non-overlap invariant across edition time ranges (inclusive bounds) at both the config-set and summaries-data schema layers. The algorithm — sort by startTime, check adjacent pairs — is correct and well-tested, covering interior overlaps, touching edges, different subregistries by chain/address, and mixed recognized/unrecognized models.

Confidence Score: 5/5

Safe to merge — the overlap detection algorithm is correct, all edge cases are tested, and the refactoring is clean.

No P0 or P1 findings. The sort-then-adjacent-check algorithm correctly detects any interval overlap (standard interval scheduling proof applies). Inclusive-bound semantics are consistently implemented and tested across all three enforcement points (validateReferralProgramEditionConfigSet, the config-set transform, and the summaries superRefine). Fixtures in existing tests were correctly adjusted to stay disjoint under the new invariant.

No files require special attention.

Important Files Changed

Filename Overview
packages/ens-referrals/src/edition.ts Extracts BaseReferralProgramEditionConfig, adds findOverlappingEditionPair (sort-by-startTime + adjacent-pair check), and wires the overlap check into validateReferralProgramEditionConfigSet. Algorithm is correct.
packages/ens-referrals/src/api/zod-schemas.ts Adds overlap check via superRefine to makeReferralProgramEditionSummariesDataSchema and inside the transform of makeReferralProgramEditionConfigSetArraySchema; removes now-duplicate makeReferralProgramEditionConfigBaseSchema in favour of the shared version.
packages/ens-referrals/src/award-models/shared/api/zod-schemas.ts Moves makeReferralProgramEditionSlugSchema here (now using shared REFERRAL_PROGRAM_EDITION_SLUG_PATTERN), adds makeBaseReferralProgramEditionConfigSchema, and refactors makeBaseReferralProgramEditionSummarySchema to extend it — tightening slug validation from min(1) to regex-checked.
packages/ens-referrals/src/award-models/shared/edition-summary.ts BaseReferralProgramEditionSummary now extends BaseReferralProgramEditionConfig, removing the duplicate slug/displayName/rules declarations.
packages/ens-referrals/src/edition.test.ts New test file covering findOverlappingEditionPair and buildReferralProgramEditionConfigSet for disjoint, interior-overlap, touching-edge, and cross-subregistry scenarios.
packages/ens-referrals/src/api/zod-schemas.test.ts Adds non-overlapping invariant test suites for both makeReferralProgramEditionConfigSetArraySchema and makeReferralProgramEditionSummariesDataSchema; adjusts fixture time ranges to be disjoint so existing tests remain valid.
packages/ens-referrals/src/internal.ts Re-exports per-award-model Zod schemas (pie-split, rev-share-cap, shared) via the internal entry point as documented in the changeset.
apps/ensapi/src/handlers/ensanalytics/ensanalytics-api.test.ts Mock leaderboards now carry each edition's own rules so cached summaries have distinct time ranges and don't trip the new non-overlap invariant.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["Array of editions"] --> B["Group by chainId:address key"]
    B --> C{"Group size >= 2?"}
    C -- No --> G["Next group"]
    C -- Yes --> D["Sort group by startTime"]
    D --> E["Iterate adjacent pairs i, i-1"]
    E --> F{"curr.startTime <= prev.endTime?"}
    F -- Yes --> H["Return overlapping pair [prev, curr]"]
    F -- No --> I{"More pairs?"}
    I -- Yes --> E
    I -- No --> G
    G --> J{"More groups?"}
    J -- Yes --> C
    J -- No --> K["Return null (no overlap)"]
    H --> L["Zod ctx.addIssue / throw Error"]
    K --> M["Validation passes"]
Loading

Reviews (3): Last reviewed commit: "review" | Re-trigger Greptile

Comment thread packages/ens-referrals/src/edition.ts
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Prevents a single referral from matching multiple referral program editions by enforcing a per-subregistryId time-range non-overlap invariant (with inclusive bounds), and refactors shared edition config fields/types to be reused across configs and summaries.

Changes:

  • Introduces BaseReferralProgramEditionConfig and uses it as a shared parent for edition configs and base edition summaries.
  • Adds findOverlappingEditionPair / validateNonOverlappingEditionTimes and enforces the invariant in both config-set building and Zod parsing (including forward-compatible/unrecognized editions).
  • Adds/updates tests and fixtures to reflect inclusive-bound overlap behavior; exposes award-model Zod schemas via @namehash/ens-referrals/internal.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/ens-referrals/src/internal.ts Re-exports per-award-model and shared Zod schemas via the internal entrypoint.
packages/ens-referrals/src/edition.ts Adds shared base config type and overlap detection/validation; enforces invariant when building config sets.
packages/ens-referrals/src/edition.test.ts New unit tests for overlap detection/validation and config-set building.
packages/ens-referrals/src/award-models/shared/edition-summary.ts Refactors base summary to extend the shared base edition config type.
packages/ens-referrals/src/award-models/shared/api/zod-schemas.ts Adds shared Zod schemas for edition slug and base edition config; reuses them in base summary schema.
packages/ens-referrals/src/api/zod-schemas.ts Reuses shared schemas; enforces the non-overlap invariant in config-set array parsing and summaries response parsing.
packages/ens-referrals/src/api/zod-schemas.test.ts Updates fixtures and adds test coverage for the non-overlap invariant (configs and summaries).
apps/ensapi/src/handlers/ensanalytics/ensanalytics-api.test.ts Updates test setup to avoid summaries collapsing to overlapping windows by ensuring per-edition rules propagate into mock leaderboards.
.changeset/shiny-tigers-wander.md Changeset for rejecting overlapping editions invariant.
.changeset/quiet-mirrors-shine.md Changeset for exposing per-award-model Zod schemas via internal entrypoint.
.changeset/bright-rivers-flow.md Changeset for adding BaseReferralProgramEditionConfig as a shared parent type.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Member

@lightwalker-eth lightwalker-eth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Goader Nice work! 1 small question only. Please take the lead to merge when ready 👍

Comment thread packages/ens-referrals/src/edition.ts Outdated
throw new Error(`Duplicate edition config slugs detected: ${duplicates.join(", ")}`);
}

validateNonOverlappingEditionTimes(configs);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a special reason not to merge this idea into the existing validateReferralProgramEditionConfigSet function?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No reason, just missed it. Thank you!

Copilot AI review requested due to automatic review settings April 24, 2026 23:34
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io April 24, 2026 23:34 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io April 24, 2026 23:34 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io April 24, 2026 23:34 Inactive
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Prevents referral program editions from overlapping in time for the same subregistryId (inclusive bounds), tightening the referrals data model invariants and adding forward-compatible validation for both configs and summaries.

Changes:

  • Introduces BaseReferralProgramEditionConfig and reuses it across config + summary types.
  • Adds overlap detection (findOverlappingEditionPair) and enforces it in config-set validation and Zod parsing (including unrecognized award models).
  • Adds/updates tests to cover overlap rejection and adjusts fixtures to be non-overlapping.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/ens-referrals/src/internal.ts Re-exports additional award-model Zod schemas via the internal entrypoint.
packages/ens-referrals/src/edition.ts Adds base config type + overlap detection/validation for edition config sets.
packages/ens-referrals/src/edition.test.ts New unit tests for overlap detection and config set invariant enforcement.
packages/ens-referrals/src/award-models/shared/edition-summary.ts Makes base summary reuse the new base config shape.
packages/ens-referrals/src/award-models/shared/api/zod-schemas.ts Adds shared base config + slug schemas; refactors base summary schema.
packages/ens-referrals/src/api/zod-schemas.ts Enforces non-overlap in config arrays and edition summaries responses.
packages/ens-referrals/src/api/zod-schemas.test.ts Adds overlap-invariant tests and updates fixtures to remain valid under inclusive bounds.
apps/ensapi/src/handlers/ensanalytics/ensanalytics-api.test.ts Updates mock leaderboards to avoid violating the new summaries non-overlap invariant.
docs/ensnode.io/ensapi-openapi.json Bumps documented OpenAPI version.
.changeset/shiny-tigers-wander.md Changeset for rejecting overlapping editions.
.changeset/quiet-mirrors-shine.md Changeset for exposing per-award-model Zod schemas via internal entrypoint.
.changeset/bright-rivers-flow.md Changeset for adding BaseReferralProgramEditionConfig.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/ens-referrals/src/edition.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/ens-referrals/src/edition.test.ts`:
- Around line 79-86: The test's regex in the expectation for
buildReferralProgramEditionConfigSet relies on a specific ordering of slugs ("a"
before "b") which makes it brittle; update the test to either (a) assert
ordering-independent presence by checking that both /"a"/ and /"b"/ appear in
the thrown message and that the subregistry id
(0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85) is present, or (b) derive the
expected ordering from findOverlappingEditionPair (using makePieSplitEdition to
build the inputs and calling findOverlappingEditionPair to determine prev/curr)
and then assert the exact tuple format in the error message — adjust the expect
in edition.test.ts to use one of these approaches so tests don't depend on an
implementation-specific ordering.
- Around line 37-102: Add a test covering a 3+ edition input where the
overlapping pair is non‑adjacent in the input order but adjacent after
sort-by-startTime: create editions like a = makePieSplitEdition("a",1000,1200),
b = makePieSplitEdition("b",2300,3000), c = makePieSplitEdition("c",1500,2500)
then call findOverlappingEditionPair([c, a, b]) and assert the returned pair is
the overlapping (c,b) with the expected slug order; mirror a similar scenario
for buildReferralProgramEditionConfigSet if desired to ensure it throws when
those two share a subregistry.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 040d4ad0-4816-4317-aa6b-e49a400793b0

📥 Commits

Reviewing files that changed from the base of the PR and between 4244d61 and 346fb88.

📒 Files selected for processing (2)
  • packages/ens-referrals/src/edition.test.ts
  • packages/ens-referrals/src/edition.ts

Comment thread packages/ens-referrals/src/edition.test.ts
Comment thread packages/ens-referrals/src/edition.test.ts Outdated
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io April 25, 2026 00:25 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io April 25, 2026 00:25 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io April 25, 2026 00:25 Inactive
@Goader Goader merged commit aa26180 into main Apr 25, 2026
20 checks passed
@Goader Goader deleted the task/prevent-edition-overlap branch April 25, 2026 00:59
@github-actions github-actions Bot mentioned this pull request Apr 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prevent overlapping referral program editions

3 participants